/*
 * main.cpp
 *
 *  Created on: 22 nov 2011
 *      Author: Robert
 */


// 1. Simulation Framework (Simulation, World, Unit/Object)
// 2. Simulation Implementation
// 3. Object Simulation Framework


class SimulationUI
{
	public:
		SimulationUI(Simulation &simulation);
		void open();
		void close();
};

class Object
{
  public:
    Object();
};


int main()
{
	Simulation sim = new Simulation();
	SimulationController simcontrol = new SimulationController(sim);


	sim.addObject(new Simulation1::Object1());

	simcontrol.run();

	sim.addEventListener(OBJECT_ADDED, EventListener(&Simulator::objectAddedListener, sim));


}


class SomeObject
{
public:
	void eventOne(Event &event);
	void eventTwo(Event &event);
};




void test()
{
	SomeObject obj = new SomeObject();

	EventListener listener = new EventListener(obj, &SomeObject::eventOne);

	Event event = new Event();

	listener(event);
}




class SimulatorObjectAddedHandler
{
public:
	SimulatorObjectAddedHandler(Simulator &sim) : simulator(sim) {}
	void operator()(const Event &event) {
		simulator.objectAddedHandler();
	}
private:
	Simulator &simulator;
};

class Simulation : public EventDispatcher
{

	// Control interface
	public:
		void step();
		void start();
		void pause();
		void running() const;
		void reset();

	// Display interface
	public:
		struct ObjectState {
			int id;
			int color;
			vector2d position;
			vector2d attitude;
			vector2d velocity;
		};
		Box getBox() const;
		vector<ObjectState> getObjects() const;
		// OBJECT_ADDED
		// OBJECT_REMOVED
		// OBJECT_CHANGED

};

class SimulationUI
{
	public:
		SimulationUI(Simulation &simulation);
		void open();
		void close();
};

class Object
{
  public:
    Object();
};


int main()
{
	Simulation sim = new Simulation();
	SimulationController simcontrol = new SimulationController(sim);


	sim.addObject(new Simulation1::Object1());

	simcontrol.run();
}

// Simulator
// - World
// - Object

// simulator.device.Device
// simulator.device.Sensor
// simulator.decive.Radar
// simulator.processor.Processor
// simulator.processor.ActiveProcessor
// simulator.processer.PassiveProcessor

// Simulation of object internals
// Simulation of world (physics)
// World Display
// Object Displays/UI/Apps

// Layers:
// - Simulation controller
// - Object OS/Processors
// - Framework (data types, commands, pipes, etc)
// - UI

// Timestep:
// - World; move objects, collision detection, etc
// - Object; devices, processors
// - Displays


// Manipulator, Actuator
// ProximitySensor

// InertialNavigationSystem

// LinearAccelerometer
// AngularAccelerometer


/**
 * An autonomous object in the world, only describing what's relevant to the outside world
 */
class WorldObject
{
	int positionX;
	int positionY;
	int attitudeX;
	int attitudeY;
};


/**
 * The world is the simulated reality, made up of autonomous objects, inanimate objects and other
 * imaginary limits, controlled by arbitrary rules set by the world.
 */
class World
{
	vector<WorldObject> objects;
};


// A device is the only means by which an autonomous object can gain information about the world
// or affect anything outside itself.
class Device
{
	World world;
	Object object;
};


// The autonomous object itself. It has no direct access to the world, and is constituted by
// knowledge about itself, devices, and its own systems.
class Object
{
	void addDevice(Device &device);
	void addToWorld(World &world);

	World const world;
	vector<Device> devices;
};


// === IMPLEMENTATION ===

class Ship : Object
{
	public:
		Ship();

	protected:
		// Sensors
		ProximitySensor proximityFront;
		ProximitySensor proximityRight;
		ProximitySensor proximityAft;
		ProximitySensor proximityLeft;

		// Actuators
		Engine engine;

		// Processors
		Autopilot autopilot;
};
Ship::Ship()
: proximityFront(0,1)
, proximityRight(1,0)
, proximityAft(0,-1)
, proximityLeft(-1,0)
{
	// Connections


}


class ProximitySensor : Device
{
	public:
		ProximitySensor(int attitudeX, int attitudeY);

		double value();

	protected:
		int aX, aY;
};
double ProximitySensor::value()
{
	if(world) {

	}
	else {
		return NaN;
	}
}


class Engine
{
	void stepForward();
	void turnLeft();
	void turnRight();
};

class WorldObject
{
	position;
	attitude;
	color;

};



class AutoPilot : ActiveProcessor
{
	Input radar;
	Output engine;

	void process()
	{
		engine.power = 0;
		engine.direction = 0;
	}
};


class SensorData
{

	// payload
};

// Connection<Data>
// .input &Input
// .output &Output
// ObjectA.output Output<Data> *Connection
// ObjectB.input Input<Data> *Connection
// ObjectB.input = (ObjectA.output = ObjectC.input);

class Input;
class Output;

class Connection
{
	private:
		Connection(Input &in, Output &out) : input(in), output(out) {
			in.connection = this;
			out.connection = this;
		}
		~Connection() {
			in.connection = 0;
			out.connection = 0;
		}
		Input &input;
		Output &output;
};
class Input
{
	public:
		Input() : connection(0) {}
		~Input() {
			disconnect();
		}
		void operator=(Output &output) {
			if(*this == output) {
				return;
			}
			connection = new Connection(*this, output);
		}
		// Input == Output is true if they are connected to each other.
		bool operator==(Output &output) {
			return connection && connection == output.connection;
		}
		void disconnect() {
			delete connection;
		}

	private:
		Connection *connection;
		friend class Connection;
};

class Output
{
	public:
		Output() : connection(0) {}
		~Output() {
			disconnect();
		}
		void disconnect() {
			delete connection;
		}

	private:
		Connection *connection;
		friend class Connection;
};

template<T>
class Input<T> : Input
{

};

// V2 guidance systems combined two gyroscopes and a lateral accelerometer with
// a simple analog computer to adjust the azimuth for the rocket in flight.
// Analog computer signals were used to drive four external rudders on the tail
// fins for flight control. The GN&C (Guidance, Navigation, and Control) system
// for V2 provided many innovations as an integrated platform with closed loop guidance.
